package com.ifacebox.client.tools;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.fastjson.JSON;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;

import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.util.*;
import java.util.List;

/**
 * @author znn
 */
public class SspPlaceSearchGui extends JFrame implements ActionListener {
    private JFileChooser jFileChooser;
    private final JToolBar jToolBar;
    private JButton jButtonChooser, jButtonSearch, jButtonConfig;
    private final JTable jTableSearch;
    private DefaultTableModel tableModelSearch;
    private final JLabel jLabelStatus;
    private JPanel jPanelConfig;
    private JTextField jTextFieldAk;
    private final SspPlaceSearchConfig config;

    public SspPlaceSearchGui() {
        super.setTitle("百度聚屏POI位置搜索工具 - POI文件内容规则（|编号|区域|名称|地址|）");
        super.setIconImage(new ImageIcon(SspConstants.LOGO_URL).getImage());
        super.setPreferredSize(new Dimension(800, 600));
        super.setLayout(new BorderLayout());
        super.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
        super.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        super.add(jToolBar = new JToolBar(), BorderLayout.NORTH);
        super.add(new JScrollPane(jTableSearch = new JTable()), BorderLayout.CENTER);
        super.add(jLabelStatus = new JLabel(String.format(SspPlaceSearchConstants.PLACE_SEARCH_STATUS_INFO, 0, 0, 0)), BorderLayout.SOUTH);
        this.initComponents();
        super.pack();
        super.setLocationRelativeTo(null);
        this.config = this.readConfig();
    }

    public void initComponents() {
        jFileChooser = new JFileChooser();
        jFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        jFileChooser.setAcceptAllFileFilterUsed(false);
        jFileChooser.addChoosableFileFilter(new FileNameExtensionFilter(SspConstants.EXCEL_EXTENSION_DESCRIPTION, SspConstants.EXCEL_EXTENSION));
        jToolBar.add(jButtonChooser = new JButton("选择POI文件"));
        jToolBar.add(jButtonSearch = new JButton("搜索POI位置"));
        jToolBar.add(jButtonConfig = new JButton("参数配置"));
        jButtonChooser.addActionListener(this);
        jButtonSearch.addActionListener(this);
        jButtonConfig.addActionListener(this);
        jTableSearch.setRowHeight(30);
        jTableSearch.setModel(tableModelSearch = new DefaultTableModel(null, SspPlaceSearchConstants.PLACE_SEARCH_TABLE_COLUMN_NAME));
        jPanelConfig = new JPanel();
        jPanelConfig.add(new Box(BoxLayout.Y_AXIS) {{
            this.add(SspUtils.addFieldBox("AK : ", jTextFieldAk = new JTextField(32)));
        }});
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == jButtonChooser) {
            if (JFileChooser.APPROVE_OPTION == jFileChooser.showOpenDialog(this)) {
                SspUtils.runThread(this::fileChooser, "Thread-Chooser");
            }
        }
        if (e.getSource() == jButtonSearch) {
            SspUtils.runThread(this::fileSearch, "Thread-Search");
        }
        if (e.getSource() == jButtonConfig) {
            this.saveConfig();
        }
    }

    public void fileChooser() {
        File file = jFileChooser.getSelectedFile();
        if (!file.isFile() || !Arrays.asList(SspConstants.EXCEL_EXTENSION).contains(FilenameUtils.getExtension(file.getName()))) {
            JOptionPane.showMessageDialog(this, "选择的POI文件错误！（|编号|区域|名称|地址|）", jButtonChooser.getText(), JOptionPane.ERROR_MESSAGE);
            return;
        }
        jButtonChooser.setEnabled(false);
        jButtonSearch.setEnabled(false);
        tableModelSearch.setRowCount(0);
        EasyExcel.read(file, new ReadListener<Map<Integer, String>>() {
            @Override
            public void invoke(Map<Integer, String> map, AnalysisContext analysisContext) {
                SwingUtilities.invokeLater(() -> {
                    tableModelSearch.addRow(new Object[]{map.get(0), map.get(1), map.get(2), map.get(3)});
                    jLabelStatus.setText(String.format(SspPlaceSearchConstants.PLACE_SEARCH_STATUS_INFO, tableModelSearch.getRowCount(), 0, 0));
                });
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                jButtonChooser.setEnabled(true);
                jButtonSearch.setEnabled(true);
                jLabelStatus.setText(String.format(SspPlaceSearchConstants.PLACE_SEARCH_STATUS_INFO, tableModelSearch.getRowCount(), 0, 0));
            }
        }).sheet().doRead();
    }

    public void fileSearch() {
        SwingUtilities.invokeLater(() -> {
            jButtonChooser.setEnabled(false);
            jButtonSearch.setEnabled(false);
        });
        SspPlaceSearchManager manager = new SspPlaceSearchManager(config);
        jLabelStatus.setText("正在搜索全部POI位置请稍后...");
        int ok = 0, no = 0;
        long ms = System.currentTimeMillis();
        System.out.printf("搜索开始：%d%n", tableModelSearch.getRowCount());
        for (int i = 0; i < tableModelSearch.getRowCount(); i++) {
            String region = (String) tableModelSearch.getValueAt(i, 1);
            String name = (String) tableModelSearch.getValueAt(i, 2);
            String address = (String) tableModelSearch.getValueAt(i, 3);
            int row = i;
            SwingUtilities.invokeLater(() -> {
                jTableSearch.setRowSelectionInterval(row, row);
                jTableSearch.scrollRectToVisible(jTableSearch.getCellRect(row, 0, true));
            });
            long mss = System.currentTimeMillis();
            System.out.printf("%d.搜索开始：%s-%s-%s%n", i, region, name, address);
            try {
                manager.searchPlace(region, name, address);
                ok++;
            } catch (Exception e) {
                System.err.printf("%d.搜索异常：%s%n", i, e.getMessage());
                tableModelSearch.setValueAt(String.format("ERR：%s", e.getMessage()), i, 4);
                no++;
            }
            System.out.printf("%d.搜索完成：%d%n", i, (System.currentTimeMillis() - mss));
            jLabelStatus.setText(String.format(SspPlaceSearchConstants.PLACE_SEARCH_STATUS_INFO, tableModelSearch.getRowCount(), ok, no));
        }
        if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(this
                , "搜索完成，是否保存搜索结果？", jButtonSearch.getText(), JOptionPane.YES_NO_OPTION)) {
            if (JFileChooser.APPROVE_OPTION == jFileChooser.showSaveDialog(this)) {
                File file = jFileChooser.getSelectedFile();
                jLabelStatus.setText("正在导出数据，请稍后...");
                List<List<String>> head = new ArrayList<>();
                for (String col : SspPlaceSearchConstants.PLACE_SEARCH_TABLE_COLUMN_NAME) {
                    head.add(new ArrayList<>(Collections.singletonList(col)));
                }
                EasyExcel.write(new File(file.getParentFile(), FilenameUtils.getBaseName(file.getName()) + ".xls"))
                        .head(head).sheet("").doWrite(tableModelSearch.getDataVector());
                jLabelStatus.setText(String.format(SspPlaceSearchConstants.PLACE_SEARCH_STATUS_INFO, tableModelSearch.getRowCount(), ok, no));
            }
        }
        System.out.printf("搜索完成：%d%n", (System.currentTimeMillis() - ms));
        jButtonChooser.setEnabled(true);
        jButtonSearch.setEnabled(true);
    }

    public void saveConfig() {
        SspPlaceSearchConfig config = this.readConfig();
        if (JOptionPane.OK_OPTION == JOptionPane.showConfirmDialog(this, jPanelConfig, jButtonConfig.getText(), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE)) {
            this.writeConfig(config);
        }
    }

    public SspPlaceSearchConfig readConfig() {
        SspPlaceSearchConfig config = new SspPlaceSearchConfig(SspPlaceSearchConstants.AK);
        if (SspPlaceSearchConstants.PLACE_SEARCH_CONFIG_FILE.exists()) {
            try {
                config = JSON.parseObject(FileUtils.readFileToByteArray(SspPlaceSearchConstants.PLACE_SEARCH_CONFIG_FILE), SspPlaceSearchConfig.class);
            } catch (Exception e) {
                JOptionPane.showMessageDialog(this, "读取配置失败！(" + e.getMessage() + ")", jButtonConfig.getText(), JOptionPane.ERROR_MESSAGE);
            }
        }
        jTextFieldAk.setText(config.getAk());
        return config;
    }

    public void writeConfig(SspPlaceSearchConfig config) {
        config.setAk(jTextFieldAk.getText());
        try {
            FileUtils.writeByteArrayToFile(SspPlaceSearchConstants.PLACE_SEARCH_CONFIG_FILE, JSON.toJSONBytes(config));
        } catch (Exception e) {
            JOptionPane.showMessageDialog(this, "保存配置失败！(" + e.getMessage() + ")", jButtonConfig.getText(), JOptionPane.ERROR_MESSAGE);
        }
    }

    public static void main(String[] args) throws Exception {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        new SspPlaceSearchGui().setVisible(true);
    }
}
